﻿using System;
using System.Collections.Generic;
using Utility.PoolSystem;

namespace Utility.DataSystem
{
	public interface IFieldEventListener
	{
		string Name { get; }
		void OnEvent (IDataFieldContext context, FieldEvent e, out bool interested);
	}

	public class FieldEventListeners : IDisposable, IPoolCallback
	{
		static SimplePool<FieldEventListeners> Pool { get; } = new SimplePool<FieldEventListeners> (() => new FieldEventListeners ());
		static HashSet<IFieldEventListener> RemoveSet { get; } = new HashSet<IFieldEventListener> ();

		public static FieldEventListeners New () => Pool.Spawn ();

		public void Dispose ()
		{
			Pool.Despawn (this);
		}

		void IPoolCallback.OnSpawn ()
		{
			set.Clear ();
		}

		void IPoolCallback.OnDespawn ()
		{
			set.Clear ();
		}


		FieldEventListeners () { }
		HashSet<IFieldEventListener> set = new HashSet<IFieldEventListener> ();

		public bool IsEmpty => set.Count == 0;

		public void Add (IFieldEventListener listener)
		{
			set.Add (listener);
		}

		public void Add (IEnumerable<IFieldEventListener> listeners)
		{
			set.AddRange (listeners);
		}

		public void OnEventAndFilter (IDataFieldContext context, FieldEvent e)
		{
			var msg = FieldCenter.GetDebugMsg (e);

			RemoveSet.Clear ();
			bool interested;

			foreach (var listener in set)
			{
				if (listener != null)
				{
					msg?.StartListener (listener);
					listener.OnEvent (context, e, out interested);
					if (!interested)
					{
						RemoveSet.Add (listener);
					}
					msg?.EndListener (listener, !interested);
				}
			}
			//filter
			RemoveSet.Add (null);
			set.ExceptWith (RemoveSet);
			RemoveSet.Clear ();
		}

		public void OnEvent (IDataFieldContext context, FieldEvent e)
		{
			var msg = FieldCenter.GetDebugMsg (e);

			foreach (var listener in set)
			{
				if (listener != null)
				{
					msg?.StartListener (listener);
					listener.OnEvent (context, e, out _);
					msg?.EndListener (listener);
				}
			}
		}
	}
}
